package cn.bearspark.happening.provider.dao.mapper;

import cn.bearspark.common.enumeration.VisibilityEnum;
import cn.bearspark.framework.redis.starter.buffer.hash.un.RedisHashMapper;
import cn.bearspark.happening.provider.dao.co.HappeningCO;
import cn.bearspark.happening.provider.dao.po.HappeningBasePO;
import cn.bearspark.happening.provider.dao.po.UserHappeningCntPO;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 动态的基础数据的映射接口
 *
 * @author f
 */
@Mapper
public interface HappeningBaseMapper extends RedisHashMapper<HappeningCO> {

    /**
     * 添加动态基础数据到数据库中
     *
     * @param happeningBasePO 动态的基础数据
     */
    void insert(HappeningBasePO happeningBasePO);

    /**
     * 批量修改动态的可见性，用于定时发布动态的功能
     *
     * @param visibility      动态的可见性
     * @param happeningIdList 动态的 id 集合
     */
    void updateVisibility(Integer visibility, List<Long> happeningIdList);

    /**
     * 获取指定用户自己发布的动态信息的条数
     *
     * @param userId      指定的用户 id
     * @param privateCode 仅自己可见的可见性的枚举值
     * @return 自己动态信息的条数
     * @see VisibilityEnum
     */
    int countSelfHappenings(long userId, int privateCode);

    /**
     * 获取指定用户发布的动态 id，按照时间倒序排序
     *
     * @param userId  指定的用户 id
     * @param offset  偏移量
     * @param limit   限制返回的数据条数
     * @param visCode 可见性的枚举值
     * @return 动态 id的集合
     * @see VisibilityEnum
     */
    List<Long> listUserHappeningsId(long userId, int offset, int limit, int visCode);

    /**
     * 获取指定用户和其关注者发布的动态信息的条数
     *
     * @param userId         指定的用户 id
     * @param followerIdList 指定用户关注者的 id 集合
     * @param publicCode     公开的可见性的枚举值
     * @param privateCode    仅自己可见的可见性的枚举值
     * @return 自己和关注者动态信息的条数
     * @see VisibilityEnum
     */
    int countUserHappenings(long userId, List<Long> followerIdList, int publicCode, int privateCode);

    /**
     * 获取指定用户和其关注者发布的动态 id，按照时间倒序排序
     *
     * @param userId         指定的用户 id
     * @param followerIdList 指定用户关注者的 id 集合
     * @param offset         偏移量
     * @param limit          限制返回的数据条数
     * @param publicCode     公开的可见性的枚举值
     * @param privateCode    仅自己可见的可见性的枚举值
     * @return 动态 id 的集合
     * @see VisibilityEnum
     */
    List<Long> listSAFHappeningsId(long userId, List<Long> followerIdList, int offset, int limit,
                                   int publicCode, int privateCode);

    @Override
    List<HappeningCO> listHotData(Set<Long> happeningIdSet);

    @Override
    List<HappeningCO> listData(List<Long> happeningIdList);

    /**
     * 增加指定动态的点赞数量
     *
     * @param happeningId 指定的动态 id
     */
    @Update("UPDATE t_happening_base SET like_num = like_num + 1 WHERE happening_id = #{happeningId}")
    void incrLikeNum(long happeningId);

    /**
     * 减少指定动态的点赞数量
     *
     * @param happeningId 指定的动态 id
     */
    @Update("UPDATE t_happening_base SET like_num = like_num - 1 WHERE happening_id = #{happeningId}")
    void decrLikeNum(long happeningId);

    /**
     * 删除指定动态的基础数据
     *
     * @param happeningId 指定的动态 id
     */
    @Delete("DELETE FROM t_happening_base WHERE happening_id = #{happeningId}")
    void deleteById(long happeningId);

    /**
     * 统计指定用户可以浏览的指定动态的数量
     *
     * @param userId      指定的用户 id
     * @param happeningId 指定的动态 id
     * @param publicCode  公开的可见性的枚举值
     * @return 指定用户可以浏览的指定动态的数量
     */
    @Select("SELECT COUNT(*) FROM t_happening_base " +
            "WHERE happening_id = #{happeningId} AND (user_id = #{userId} OR visibility = #{publicCode})")
    int count(long userId, long happeningId, int publicCode);

    /**
     * 查询指定用户最后一次发布动态的时间
     *
     * @param userId 指定的用户 id
     * @return 指定用户最后一次发布动态的时间
     */
    @Select("SELECT MAX(pub_time) FROM t_happening_base WHERE user_id = #{userId}")
    Date getLastPubTime(long userId);

    /**
     * 修改动态的基础数据
     *
     * @param happeningId 待修改的动态 id
     * @param tagId       修改后的动态的标签 id，可以为 null
     * @param title       修改后的动态的标题，可以为 null
     * @param visibility  修改后的动态的可见性
     */
    void update(long happeningId, Long tagId, String title, int visibility);

    /**
     * 增加指定引用动态的转发数
     *
     * @param quotedHappeningId 指定引用动态的 id
     */
    @Update("UPDATE t_happening_base SET forward_num = forward_num + 1 WHERE happening_id = #{quotedHappeningId}")
    void incrForwardNum(long quotedHappeningId);

    /**
     * 增加动态的评论数
     *
     * @param happeningId 待增加评论数的动态 id
     */
    @Update("UPDATE t_happening_base SET comment_num = comment_num + 1 WHERE happening_id = #{happeningId}")
    void incrCommentNum(long happeningId);

    /**
     * 减少动态的评论数
     *
     * @param happeningId 待减少评论数的动态 id
     * @param decrement   减少的评论数
     */
    @Update("UPDATE t_happening_base SET comment_num = comment_num - #{decrement} WHERE happening_id = #{happeningId}")
    void decrCommentNum(long happeningId, long decrement);

    /**
     * 统计指定用户的动态数，仅统计非不可见的动态
     *
     * @param userIdList 指定的用户 id 集合
     * @param visCode    不可见动态的枚举值
     * @return 指定用户的动态数集合
     */
    List<UserHappeningCntPO> countUsersHappening(List<Long> userIdList, int visCode);
}
